<?php
/**
 * 图像处理类
 *
 * [Code]
 * $h = App::h('Image')
 * $h->init($file);
 * $h->setDir('');
 * $h->save();
 * [/Code]
 *
 * @version $Id: Image.php 90 2013-05-21 08:40:21Z linsir123 $
 * @package Helper
 */
class HelperImage
{
	/**
	 * 展示图像MIMES
	 *
	 * @var array
	 * @static
	 */
	static $ext2Mime = array(
		'png' => 'image/png',
		'gif' => 'image/gif', 'jpg' => 'image/jpeg'
	);

	/**
	 * 输出函数
	 *
	 * @var array
	 * @static
	 */
	static $ext2Display = array(
		'png' => 'imagepng',
		'gif' => 'imagegif', 'jpg' => 'imagejpeg'
	);

	/**
	 * 创建函数
	 *
	 * @var array
	 * @static
	 */
	static $ext2Create = array(
		'png' => 'imagecreatefrompng',
		'gif' => 'imagecreatefromgif', 'jpg' => 'imagecreatefromjpeg'
	);

	/**
	 * 文件保存的路径
	 *
	 * @var string
	 */
	private $_saveDir;

	/**
	 * 文件后缀
	 *
	 * @var string
	 */
	private $_fileExt;

	/**
	 * 文件保存的文件名
	 *
	 * @var string
	 */
	private $_fileName;

	/**
	 * 创建函数
	 *
	 * @var string
	 */
	private $_func2Create;

	/**
	 * 输出函数
	 *
	 * @var string
	 */
	private $_func2Display;

	/**
	 * 图像句柄
	 *
	 * @var resource
	 */
	private $_im;

	/**
	 * 图片宽度
	 *
	 * @var int
	 */
	private $_width;

	/**
	 * 图片高度
	 *
	 * @var int
	 */
	private $_height;

	/**
	 * 构造函数
	 *
	 * @param string $file 待处理的图片地址
	 */
	public function init($file)
	{
		$info = getimagesize($file);
		$ext = array_search($info['mime'], self::$ext2Mime);
		if (! empty($info) && ! empty($ext) && file_exists($file)) {
			$this->_func2Display = self::$ext2Display[$ext];
			$this->_func2Create = self::$ext2Create[$ext];
			$this->_fileExt = $ext;

			///
			$im = call_user_func_array($this->_func2Create, array($file));
			$this->_setIm($im);

			/* PNG 透明处理(创建透明填充色) */
			if ($this->_fileExt == 'png') {
				imagealphablending($this->_im, true);
				imagesavealpha($this->_im, true);
			}
		}
	}

	/**
	 * 水印文本
	 * // 可以设置"size", "angle", "alpha", "color"几个属性
	 *
	 * @param int $postion 位置
	 * @param string $text 文本内容
	 * @param array $params 参数列表
	 *
	 * @return bool
	 */
	public function waterText($postion, $text, $params = array())
	{
		if (empty($this->_im))
			return false;

		///
		$color = isset($params['color']) ? trim($params['color']) : '#FF0000';
		$angle = isset($params['angle']) ? intval($params['angle']) : 0;
		$alpha = isset($params['alpha']) ? intval($params['alpha']) : 0;
		$size = isset($params['size']) ? intval($params['size']) : 40;
		if (! empty($text)) {
			$colorRGB = $this->_hex2rgb($color);
			$fontPath = dirname(__FILE__) . DS . 'fonts/verdanab.ttf';
			if ($size < 0 || $size > 100)
				$size = 40;
			if ($alpha < 0 || $alpha > 100)
				$alpha = 80;

			///
			$box = imagettfbbox($size, $angle, $fontPath, $text);
			$logoHeight = max($box[1], $box[3]) - min($box[5], $box[7]);
			$logoWidth = max($box[2], $box[4]) - min($box[0], $box[6]);
			$ax = min($box[0], $box[6]) * - 1;
			$ay = min($box[5], $box[7]) * - 1;

			///
			list($x, $y) = $this->_waterPostion($postion, $logoWidth, $logoHeight);
			$color = imagecolorallocatealpha($this->_im, $colorRGB[0], $colorRGB[1], $colorRGB[2], $alpha);

			return imagettftext($this->_im, $size, $angle, $x + $ax, $y + $ay, $color, $fontPath, $text);
		}

		return false;
	}

	/**
	 * 水印图片
	 *
	 * @param int $postion 位置
	 * @param string $file 水印图片路径
	 *
	 * @return bool
	 */
	public function waterImage($postion, $file)
	{
		if (empty($this->_im))
			return false;

		///
		$ext2Create = self::$ext2Create[pathinfo($file, PATHINFO_EXTENSION)];
		if (! empty($ext2Create) && file_exists($file) && ($im = $ext2Create($file))) {
			$logoWidth = imagesx($im);
			$logoHeight = imagesy($im);

			///
			list($x, $y) = $this->_waterPostion($postion, $logoWidth, $logoHeight);
			$params = array($this->_im, $im, $x, $y, 0, 0, $logoWidth, $logoHeight);
			if ($ext2Create == 'imagecreatefrompng')
				$function = 'imagecopy';
			else {
				imagealphablending($this->_im, true);
				$function = 'imagecopymerge';
				$params[] = 65;
			}

			return call_user_func_array($function, $params);
		}

		return false;
	}

	/**
	 * 保持图像长宽比的情况下将图像裁到指定大小
	 *
	 * @param int $width 宽度
	 * @param int $height 高度
	 *
	 * @return bool
	 */
	public function thumb($width, $height = 0)
	{
		if (empty($this->_im))
			return false;

		///
		$imageWidth = $this->_width;
		$imageHeight = $this->_height;
		if (empty($width) || empty($height)) {

			/* 按一边进行缩放 */
			$width or ($width = $imageWidth);
			$height or ($height = $imageHeight);
			if ($width >= $imageWidth && $height >= $imageHeight)
				return false;

			if ($width < $imageWidth)
				$height = intval(($width / $imageWidth) * $imageHeight);
			elseif ($height < $imageHeight)
				$width = intval(($height / $imageHeight) * $imageWidth);

		}
		else {

			/* 限定于指定的宽与高内 */
			if ($width >= $imageWidth && $height >= $imageHeight)
				return false;

			if ($width > $height) {
				$height_scale = intval(($width / $imageWidth) * $imageHeight);
				if ($height_scale > $height)
					$width = intval(($height / $height_scale) * $width);
				else
					$height = $height_scale;
			}
			else {
				$width_scale = intval(($height / $imageHeight) * $imageWidth);
				if ($width_scale > $width)
					$height = intval(($width / $width_scale) * $height);
				else
					$width = $width_scale;
			}
		}

		$im = imagecreatetruecolor($width, $height);
		/* PNG 透明处理(创建透明填充色) */
		if ($this->_fileExt == 'png') {
			imagealphablending($im, true);
			imagesavealpha($im, true);
			$bgcolor = imagecolorallocatealpha($im, 0, 0, 0, 127);
			imagefill($im, 0, 0, $bgcolor);
		}

		$params = array($im, $this->_im, 0, 0, 0, 0, $width, $height, $imageWidth, $imageHeight);
		call_user_func_array('imagecopyresampled', $params);
		imagedestroy($this->_im);

		///
		$this->_setIm($im);

		return true;
	}

	/**
	 * 设置上传目录
	 *
	 * @param string $saveDir 目录物理地址
	 */
	public function setDir($saveDir)
	{
		$saveDir = str_replace(array('/', '\\'), DS, $saveDir);
		$this->_saveDir = ((substr($saveDir, - 1) == DS) ?
			substr($saveDir, 0, - 1) : $saveDir) . DS;
	}

	/**
	 * 保存图像
	 *
	 * @param string $fileName 文件名(不需要后缀)
	 *
	 * @return bool
	 */
	public function save($fileName)
	{
		if ($this->_im) {
			$this->_fileName = $fileName . '.' . $this->_fileExt;
			$desc = $this->_saveDir . $this->_fileName;

			///
			return call_user_func_array($this->_func2Display, array($this->_im, $desc));
		}

		return false;
	}

	/**
	 * 显示图像
	 */
	public function display()
	{
		if ($this->_im) {
			header("Content-type:" . self::$ext2Mime[$this->_fileExt]);
			call_user_func_array($this->_func2Display, array($this->_im));
		}
	}

	/**
	 * 取得文件的保存名称
	 * // 当文件保存成功后，取得物理地址
	 *
	 * @param bool $full 是否完整地址
	 *
	 * @return string
	 */
	public function getSaveName($full = true)
	{
		return ($full ? $this->_saveDir : '') . $this->_fileName;
	}

	/**
	 * 设置图像尺寸
	 *
	 * @param mixed $im
	 */
	private function _setIm($im = null)
	{
		$this->_im = $im;
		$this->_width = imagesx($this->_im);
		$this->_height = imagesy($this->_im);
	}

	/**
	 * 算出水印位置
	 *
	 * @param int $postion 位置
	 * @param int $logoWidth 内容宽度
	 * @param int $logoHeight 内容高度
	 *
	 * @return bool
	 */
	private function _waterPostion($postion, $logoWidth, $logoHeight)
	{
		$x = $y = 0;
		$imageWidth = $this->_width;
		$imageHeight = $this->_height;
		switch ($postion) {
			case 1:
				$x = + 5;
				$y = + 5;
				break;
			case 2:
				$x = ($imageWidth - $logoWidth) / 2;
				$y = + 5;
				break;
			case 3:
				$x = $imageWidth - $logoWidth - 5;
				$y = + 5;
				break;
			case 4:
				$x = + 5;
				$y = ($imageHeight - $logoHeight) / 2;
				break;
			case 5:
				$x = ($imageWidth - $logoWidth) / 2;
				$y = ($imageHeight - $logoHeight) / 2;
				break;
			case 6:
				$x = $imageWidth - $logoWidth;
				$y = ($imageHeight - $logoHeight) / 2;
				break;
			case 7:
				$x = + 5;
				$y = $imageWidth - $logoHeight - 5;
				break;
			case 8:
				$x = ($imageWidth - $logoWidth) / 2;
				$y = $imageHeight - $logoHeight - 5;
				break;
			case 9:
				$x = $imageWidth - $logoWidth - 5;
				$y = $imageHeight - $logoHeight - 5;
				break;
		}

		return array($x, $y);
	}

	/**
	 * 将16进制颜色值转成RGB格式
	 * // `Captcha.php`,`Image.php`组件有用到
	 *
	 * @param string $color 颜色值(16进制)
	 * @param string $defualt 默认颜色值(16进制)
	 *
	 * @return array
	 */
	private function _hex2rgb($color, $defualt = 'ffffff')
	{
		///
		$color = strtolower($color);
		if (substr($color, 0, 2) == '0x')
			$color = substr($color, 2);
		elseif (substr($color, 0, 1) == '#')
			$color = substr($color, 1);

		///
		$len = strlen($color);
		if ($len == 3)
			return array(
				hexdec(substr($color, 0, 1)),
				hexdec(substr($color, 1, 1)),
				hexdec(substr($color, 2, 1))
			);
		elseif ($len != 6)
			$color = $defualt;

		///
		return array(
			hexdec(substr($color, 0, 2)),
			hexdec(substr($color, 2, 2)),
			hexdec(substr($color, 4, 2))
		);
	}
}
